module ApiGen

class AccessDenied < Exception
end

class NotFound < Exception
end

class Entry
  attr_accessor :factory, :symbols

  def initialize
    @factory = nil
    @symbols = []
  end
end


class AccessManager

  @@REGISTRY = {}

  def self.register factory, symbol
    entry = Entry.new
    entry.factory = factory
    entry.symbols.push symbol

    @@REGISTRY[factory.name] = entry
  end

  def self.get name
    @@REGISTRY[name]
  end
end


class Resolver
  attr_accessor :symbol

  def initialize symbol
    @symbol = symbol
  end

  def v *args
    base, subpath = @symbol.split '.'

    entry = AccessManager.get base
    raise NotFound, "There's no such object" if entry.nil?

    found = entry.symbols.include?(subpath)
    raise AccessDenied, "You don't have access to this resource" if not found

    inst = entry.factory.new
    inst.send subpath.to_sym, *args
  end
end

def from_dsl description
  Resolver.new(description[:symbol]).v(*(description[:args] || []))
end

end
